#include "main.h"
#include "stm32g4xx_hal.h"

// 防抖相关定义
#define DEBOUNCE_TIME_MS    20      // 防抖时间20ms
#define SCAN_PERIOD_MS      5       // 扫描周期5ms
#define KEY_PRESSED         0       // 按键按下时的电平
#define KEY_RELEASED        1       // 按键释放时的电平

// 按键状态枚举
typedef enum 
{
    KEY_STATE_RELEASED = 0,         // 释放状态
    KEY_STATE_PRESSED,              // 按下状态
    KEY_STATE_DEBOUNCING_PRESS,     // 按下防抖中
    KEY_STATE_DEBOUNCING_RELEASE    // 释放防抖中
} key_state_enum_t;

// 按键结构体
typedef struct 
{
    uint16_t pin;                   // GPIO引脚
    GPIO_TypeDef* port;             // GPIO端口
    key_state_enum_t state;         // 当前状态
    uint32_t debounce_counter;      // 防抖计数器
    uint8_t last_raw_state;         // 上次原始状态
} key_polling_t;

// 按键实例
static key_polling_t keys[] = 
{
    {key0_Pin, key0_GPIO_Port, KEY_STATE_RELEASED, 0, KEY_RELEASED},
    {key1_Pin, key1_GPIO_Port, KEY_STATE_RELEASED, 0, KEY_RELEASED},
    {key2_Pin, key2_GPIO_Port, KEY_STATE_RELEASED, 0, KEY_RELEASED}
};

#define KEY_COUNT (sizeof(keys) / sizeof(keys[0]))
#define DEBOUNCE_COUNT (DEBOUNCE_TIME_MS / SCAN_PERIOD_MS)  // 防抖计数值

/**
 * @brief 读取按键原始状态
 */
static uint8_t read_key_raw_state(key_polling_t* key)
{
    return HAL_GPIO_ReadPin(key->port, key->pin);
}

/**
 * @brief 按键按下事件处理
 */
void key_press_event(int key_index)
{
    switch (key_index)
    {
        case 0:
            printf("KEY0 pressed\n");
            break;
        case 1:
            printf("KEY1 pressed\n");
            break;
        case 2:
            printf("KEY2 pressed\n");
            break;
        default:
            break;
    }
}

/**
 * @brief 按键释放事件处理
 */
void key_release_event(int key_index)
{
    switch (key_index)
    {
        case 0:
            printf("KEY0 released\n");
            break;
        case 1:
            printf("KEY1 released\n");
            break;
        case 2:
            printf("KEY2 released\n");
            break;
        default:
            break;
    }
}

/**
 * @brief 单个按键状态机处理
 */
static void process_key_state_machine(key_polling_t* key, int key_index)
{
    uint8_t current_raw_state = read_key_raw_state(key);
    
    switch (key->state)
    {
        case KEY_STATE_RELEASED:
            if (current_raw_state == KEY_PRESSED)
            {
                // 检测到按下，开始防抖
                key->state = KEY_STATE_DEBOUNCING_PRESS;
                key->debounce_counter = 0;
            }
            break;
            
        case KEY_STATE_DEBOUNCING_PRESS:
            if (current_raw_state == KEY_PRESSED)
            {
                key->debounce_counter++;
                if (key->debounce_counter >= DEBOUNCE_COUNT)
                {
                    // 防抖完成，确认按下
                    key->state = KEY_STATE_PRESSED;
                    key_press_event(key_index);
                }
            }
            else
            {
                // 抖动，回到释放状态
                key->state = KEY_STATE_RELEASED;
                key->debounce_counter = 0;
            }
            break;
            
        case KEY_STATE_PRESSED:
            if (current_raw_state == KEY_RELEASED)
            {
                // 检测到释放，开始防抖
                key->state = KEY_STATE_DEBOUNCING_RELEASE;
                key->debounce_counter = 0;
            }
            break;
            
        case KEY_STATE_DEBOUNCING_RELEASE:
            if (current_raw_state == KEY_RELEASED)
            {
                key->debounce_counter++;
                if (key->debounce_counter >= DEBOUNCE_COUNT)
                {
                    // 防抖完成，确认释放
                    key->state = KEY_STATE_RELEASED;
                    key_release_event(key_index);
                }
            }
            else
            {
                // 抖动，回到按下状态
                key->state = KEY_STATE_PRESSED;
                key->debounce_counter = 0;
            }
            break;
    }
    
    key->last_raw_state = current_raw_state;
}

/**
 * @brief 按键扫描函数（需要在定时器中调用）
 * @note 建议每5ms调用一次
 */
void key_scan_task(void)
{
    for (int i = 0; i < KEY_COUNT; i++)
    {
        process_key_state_machine(&keys[i], i);
    }
}

/**
 * @brief 按键轮询防抖初始化
 */
void key_polling_debounce_init(void)
{
    // 初始化按键状态
    for (int i = 0; i < KEY_COUNT; i++)
    {
        keys[i].state = KEY_STATE_RELEASED;
        keys[i].debounce_counter = 0;
        keys[i].last_raw_state = read_key_raw_state(&keys[i]);
    }
}

/**
 * @brief 获取按键当前状态
 */
uint8_t is_key_pressed(int key_index)
{
    if (key_index >= 0 && key_index < KEY_COUNT)
    {
        return (keys[key_index].state == KEY_STATE_PRESSED) ? 1 : 0;
    }
    return 0;
} 